﻿namespace Utils
{
    public static class MicrosecondTimeStamp
    {
        // 基准时间：2020-01-01 00:00:00 UTC
        private static readonly DateTime _epoch = new(2020, 1, 1, 0, 0, 0, DateTimeKind.Utc);

        // 原子计数器，用于处理同一微秒内的并发请求
        private static long _sequence;

        #region 基础方法：获取微秒数

        /// <summary>
        /// 获取自2020-01-01 00:00:00 UTC以来的微秒数
        /// </summary>
        public static long GetMicroseconds()
        {
            // DateTime.UtcNow.Ticks 精度为100纳秒（1微秒 = 10 Ticks）
            return (DateTime.UtcNow.Ticks - _epoch.Ticks) / 10;
        }

        #endregion

        #region 格式：年月日时分秒_微秒（适合文件命名）

        /// <summary>
        /// 生成格式为 "yyyyMMdd_HHmmss_ffffff" 的时间字符串（例如：20250529_153045_123456）
        /// </summary>
        public static string GenerateFileFriendlyString()
        {
            long microseconds = GetMicroseconds();
            DateTime now = _epoch.AddTicks(microseconds * 10);
            return now.ToString("yyyyMMdd_HHmmss_ffffff");
        }

        #endregion

        #region 格式：年月日时分秒微秒（紧凑格式，适合ID）

        /// <summary>
        /// 生成格式为 "yyyyMMddHHmmssffffff" 的时间字符串（例如：20250529153045123456）
        /// </summary>
        public static string GenerateCompactString()
        {
            long microseconds = GetMicroseconds();
            DateTime now = _epoch.AddTicks(microseconds * 10);
            return now.ToString("yyyyMMddHHmmssffffff");
        }

        #endregion

        #region 带序列的唯一ID（解决同一微秒内的唯一性）

        /// <summary>
        /// 生成带序列的唯一ID，格式为 "yyyyMMddHHmmssffffff序列"（例如：202505291530451234560001）
        /// </summary>
        /// <param name="maxSequencePerMicrosecond">每个微秒允许的最大序列数（默认9999）</param>
        public static string GenerateUniqueId(int maxSequencePerMicrosecond = 9999)
        {
            long microseconds = GetMicroseconds();
            DateTime now = _epoch.AddTicks(microseconds * 10);

            // 获取并递增序列（原子操作）
            long sequence = Interlocked.Increment(ref _sequence) % maxSequencePerMicrosecond;

            // 重置序列：如果时间戳变化，将序列重置为0
            if (sequence == 0)
            {
                Interlocked.Exchange(ref _sequence, 0);
            }

            return $"{now:yyyyMMddHHmmssffffff}{sequence:D4}";
        }

        #endregion

        #region 解析方法

        /// <summary>
        /// 从时间字符串解析为DateTime（支持上述所有格式）
        /// </summary>
        public static DateTime Parse(string timestamp)
        {
            // 移除可能存在的分隔符和序列部分
            string cleanString = System.Text.RegularExpressions.Regex.Replace(timestamp, @"[^0-9]", "");

            // 截取前20位（yyyyMMddHHmmssffffff）
            cleanString = cleanString.Substring(0, Math.Min(20, cleanString.Length));

            if (DateTime.TryParseExact(cleanString, "yyyyMMddHHmmssffffff",
                System.Globalization.CultureInfo.InvariantCulture,
                System.Globalization.DateTimeStyles.AssumeUniversal, out DateTime result))
            {
                return result;
            }

            throw new ArgumentException("无效的时间戳格式", nameof(timestamp));
        }

        #endregion
    }
}
